import time

import serial
import serial.tools.list_ports
from manager import SEND_TYPE
from manager.Common import *


class comManager(object):
    _instance_lock = threading.Lock()
    _first_init = True

    def __init__(self):
        if self._first_init:
            self._first_init = False
            self.com_port = None
            self.bloop = True
            self.dict_sensor = {}
        pass

    def __del__(self):
        pass

    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            with comManager._instance_lock:
                if not hasattr(cls, '_instance'):
                    comManager._instance = super().__new__(cls)
        return comManager._instance

    def init_com(self, com, baud, parity, stop, data):
        self.com_port = serial.Serial(com, baud, data, parity, stop)

    @staticmethod
    def get_com_port():
        port_list = list(serial.tools.list_ports.comports())
        device_dict = {}
        for i in range(0, len(port_list)):
            device_dict[port_list[i].name] = port_list[i].device
            print(port_list[i].name)
        return device_dict

    def open_com_port(self):
        if not self.com_port.is_open:
            self.com_port.open()
        pass

    def close_com_port(self):
        if self.com_port.is_open:
            self.com_port.close()
            self.bloop = False
            self.com_port = None
        pass

    def receive_data(self, way):
        try:
            if self.com_port.in_waiting:
                if way == 0:
                    return self.com_port.in_waiting, self.com_port.read(self.com_port.in_waiting)
                elif way == 1:
                    return self.com_port.in_waiting, self.com_port.readall().decode()
            else:
                return 0, ''
        except Exception as e:
            print("异常报错", e)

    def read_line(self):
        return self.com_port.readline()

    def send_data(self, send_type, data):
        if self.com_port is None:
            return
        if send_type == SEND_TYPE.HEX_SEND:
            hex_data = bytes.fromhex(data)
            self.com_port.write(hex_data)
        else:
            self.com_port.write(data.encode())
        print('send data: ', data)

    @staticmethod
    def change_parity(str_parity):
        parity = ''
        if str_parity == "None":
            parity = serial.PARITY_NONE
        elif str_parity == "Odd":
            parity = serial.PARITY_NAMES.PARITY_ODD
        elif str_parity == "Even":
            parity = serial.PARITY_NAMES.PARITY_EVEN
        return parity

    def data_paste(self, data: bytes):
        Common.data_paste(data, self.dict_sensor)
        return self.dict_sensor

    def station_connect(self, data: bytes):
        index = data.find(b'\xa5')
        if index != -1:
            head_hex = int(Common.bytes_to_str(data[index:index + 1]), 16)
            if head_hex == 0xA5:
                msg_id_hex = int(Common.bytes_to_str(data[index + 1:index + 2]), 16)
                if msg_id_hex == 0x01:
                    msg_id_hex1 = int(Common.bytes_to_str(data[index + 2:index + 3]), 16)
                    if msg_id_hex1 == 0x00:
                        comManager().send_data(SEND_TYPE.STRING_SEND, "AT+CIPSEND" + "\r\n")
                        time.sleep(0.3)
                        self.send_data(SEND_TYPE.HEX_SEND, 'A5 02 00 00')
                        time.sleep(0.3)
                        comManager().send_data(SEND_TYPE.STRING_SEND, "+++")
                        time.sleep(0.3)
